package com.kgc.interceptor;


import com.kgc.config.annotation.RequestPermission;
import com.kgc.exception.TokenException;
import com.kgc.exception.TokenExceptionEnum;
import com.kgc.excpt.SysException;
import com.kgc.excpt.SysExceptionEnum;
import com.kgc.util.RedisUtils;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.util.StringUtils;
import org.springframework.web.method.HandlerMethod;
import org.springframework.web.servlet.HandlerInterceptor;
import org.springframework.web.servlet.ModelAndView;

import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;


/**
 * @Classname SecurityIntercepter
 * @Description 权限校验拦截器
 * @Date 2021/6/17 16:13
 * @Created by 17402
 */
@Slf4j
public class SecurityIntercepter implements HandlerInterceptor {
    @Autowired
    public RedisUtils redisUtils;

    @Override
    public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception {
       //判断是否能要做权限校验，需要，获取token，不需要就直接放行
     if(this.checkRequestPermission(handler)){

         //获取token
         String token=request.getHeader("token");

         //非空校验
         if(StringUtils.isEmpty(token)){
             log.info("token为空，权限不足，重新登录");
             throw new SysException(SysExceptionEnum.TOKEN_ISLOST_EXCPT);
         }
         //验证是否有效
         Object userObj=redisUtils.get(token);
         if(StringUtils.isEmpty(userObj)){
             log.info("token非法或失效，权限不足，重新登录");
             throw new SysException(SysExceptionEnum.TOKEN_ISLOST_EXCPT);
         }
     }
       //直接放行，权限校验通过，或者不需要校验
        return true;
    }



    @Override
    public void postHandle(HttpServletRequest httpServletRequest, HttpServletResponse httpServletResponse, Object o, ModelAndView modelAndView) throws Exception {

    }

    @Override
    public void afterCompletion(HttpServletRequest httpServletRequest, HttpServletResponse httpServletResponse, Object o, Exception e) throws Exception {

    }
    /**
     * @description: 目标方法是否加了权限许可注解
     * @param:
     * @return:
     * @author
     */
    public boolean checkRequestPermission(Object handler){
        //判断当前handler是否映射了目标处理方法
        if (handler instanceof HandlerMethod){
            //强转为HandlerMethod对象（封装了目标处理方法）
            HandlerMethod handlerMethod=(HandlerMethod)handler;
            //获取请求处理方法上有无加请求许可注解
            RequestPermission requestPermission=handlerMethod.getMethod().getAnnotation(RequestPermission.class);
            //如果方法上取不到，不代表不需要鉴权，则看类上有无加注解
            if(requestPermission==null){
                requestPermission=handlerMethod.getMethod().getDeclaringClass().getAnnotation(RequestPermission.class);
            }
            //若获取到了注解对象，代表要进行权限校验，否则放行
            if(null!=requestPermission){
                return true;
            }
        }

        return false;
    }
}
